home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / share / automake-1.8 / Automake / DisjConditions.pm < prev    next >
Encoding:
Perl POD Document  |  2005-10-16  |  13.6 KB  |  520 lines

  1. # Copyright (C) 1997, 2001, 2002, 2003  Free Software Foundation, Inc.
  2.  
  3. # This program is free software; you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation; either version 2, or (at your option)
  6. # any later version.
  7.  
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. # GNU General Public License for more details.
  12.  
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the Free Software
  15. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  16. # 02111-1307, USA.
  17.  
  18. package Automake::DisjConditions;
  19.  
  20. use Carp;
  21. use strict;
  22. use Automake::Condition qw/TRUE FALSE/;
  23.  
  24. =head1 NAME
  25.  
  26. Automake::DisjConditions - record a disjunction of Conditions
  27.  
  28. =head1 SYNOPSIS
  29.  
  30.   use Automake::Condition;
  31.   use Automake::DisjConditions;
  32.  
  33.   # Create a Condition to represent "COND1 and not COND2".
  34.   my $cond = new Automake::Condition "COND1_TRUE", "COND2_FALSE";
  35.   # Create a Condition to represent "not COND3".
  36.   my $other = new Automake::Condition "COND3_FALSE";
  37.  
  38.   # Create a DisjConditions to represent
  39.   #   "(COND1 and not COND2) or (not COND3)"
  40.   my $set = new Automake::DisjConditions $cond, $other;
  41.  
  42.   # Return the list of Conditions involved in $set.
  43.   my @conds = $set->conds;
  44.  
  45.   # Return one of the Condition involved in $set.
  46.   my $cond = $set->one_cond;
  47.  
  48.   # Return true iff $set is always true (i.e. its subconditions
  49.   # conver all cases).
  50.   if ($set->true) { ... }
  51.  
  52.   # Return false iff $set is always false (i.e. is empty, or contains
  53.   # only false conditions).
  54.   if ($set->false) { ... }
  55.  
  56.   # Return a string representing the DisjConditions.
  57.   #   "COND1_TRUE COND2_FALSE | COND3_FALSE"
  58.   my $str = $set->string;
  59.  
  60.   # Return a human readable string representing the DisjConditions.
  61.   #   "(COND1 and !COND2) or (!COND3)"
  62.   my $str = $set->human;
  63.  
  64.   # Invert a DisjConditions, i.e., create a new DisjConditions
  65.   # that complements $set.
  66.   my $inv = $set->invert;
  67.  
  68.   # Multiply two DisjConditions.
  69.   my $prod = $set1->multiply ($set2);
  70.  
  71.   # Return the subconditions of a DisjConditions with respect to
  72.   # a Condition.  See the description for a real example.
  73.   my $subconds = $set->sub_conditions ($cond);
  74.  
  75.   # Check whether a new definition in condition $cond would be
  76.   # ambiguous w.r.t. existing definitions in $set.
  77.   ($msg, $ambig_cond) = $set->ambiguous_p ($what, $cond);
  78.  
  79. =head1 DESCRIPTION
  80.  
  81. A C<DisjConditions> is a disjunction of C<Condition>s.  In Automake
  82. they are used to represent the conditions into which Makefile
  83. variables and Makefile rules are defined.
  84.  
  85. If the variable C<VAR> is defined as
  86.  
  87.   if COND1
  88.     if COND2
  89.       VAR = value1
  90.     endif
  91.   endif
  92.   if !COND3
  93.     if COND4
  94.       VAR = value2
  95.     endif
  96.   endif
  97.  
  98. then it will be associated a C<DisjConditions> created with
  99. the following statement.
  100.  
  101.   new Automake::DisjConditions
  102.     (new Automake::Condition ("COND1_TRUE", "COND2_TRUE"),
  103.      new Automake::Condition ("COND3_FALSE", "COND4_TRUE"));
  104.  
  105. As you can see, a C<DisjConditions> is made from a list of
  106. C<Condition>s.  Since C<DisjConditions> is a disjunction, and
  107. C<Condition> is a conjunction, the above can be read as
  108. follows.
  109.  
  110.   (COND1 and COND2) or ((not COND3) and COND4)
  111.  
  112. That's indeed the condition into which C<VAR> has a value.
  113.  
  114. Like C<Condition> objects, a C<DisjConditions> object is unique
  115. with respect to its conditions.  Two C<DisjConditions> objects created
  116. for the same set of conditions will have the same adress.  This makes
  117. it easy to compare C<DisjConditions>s: just compare the references.
  118.  
  119. =head2 Methods
  120.  
  121. =over 4
  122.  
  123. =item C<$set = new Automake::DisjConditions [@conds]>
  124.  
  125. Create a C<DisjConditions> object from the list of C<Condition>
  126. objects passed in arguments.
  127.  
  128. If the C<@conds> list is empty, the C<DisjConditions> is assumed to be
  129. false.
  130.  
  131. As explained previously, the reference (object) returned is unique
  132. with respect to C<@conds>.  For this purpose, duplicate elements are
  133. ignored.
  134.  
  135. =cut
  136.  
  137. # Keys in this hash are DisjConditions strings. Values are the
  138. # associated object DisjConditions.  This is used by `new' to reuse
  139. # DisjConditions objects with identical conditions.
  140. use vars '%_disjcondition_singletons';
  141.  
  142. sub new ($;@)
  143. {
  144.   my ($class, @conds) = @_;
  145.   my $self = {
  146.     hash => {},
  147.   };
  148.   bless $self, $class;
  149.  
  150.   for my $cond (@conds)
  151.     {
  152.       confess "`$cond' isn't a reference" unless ref $cond;
  153.       confess "`$cond' isn't an Automake::Condition"
  154.     unless $cond->isa ("Automake::Condition");
  155.  
  156.       # This is a disjunction of conditions, so we drop
  157.       # false conditions.  We'll always treat an "empty"
  158.       # DisjConditions as false for this reason.
  159.       next if $cond->false;
  160.  
  161.       # Store conditions as keys AND as values, because blessed
  162.       # objects are converted to string when used as keys (so
  163.       # at least we still have the value when we need to call
  164.       # a method).
  165.       $self->{'hash'}{$cond} = $cond;
  166.     }
  167.  
  168.   my $key = $self->string;
  169.   if (exists $_disjcondition_singletons{$key})
  170.     {
  171.       return $_disjcondition_singletons{$key};
  172.     }
  173.   $_disjcondition_singletons{$key} = $self;
  174.   return $self;
  175. }
  176.  
  177. =item C<@conds = $set-E<gt>conds>
  178.  
  179. Return the list of C<Condition> objects involved in C<$set>.
  180.  
  181. =cut
  182.  
  183. sub conds ($ )
  184. {
  185.   my ($self) = @_;
  186.   return @{$self->{'conds'}} if exists $self->{'conds'};
  187.   my @conds = values %{$self->{'hash'}};
  188.   @conds = sort { $a->string cmp $b->string } @conds;
  189.   $self->{'conds'} = [@conds];
  190.   return @conds;
  191. }
  192.  
  193. =item C<$cond = $set-E<gt>one_cond>
  194.  
  195. Return one C<Condition> object involved in C<$set>.
  196.  
  197. =cut
  198.  
  199. sub one_cond ($)
  200. {
  201.   my ($self) = @_;
  202.   return (%{$self->{'hash'}},)[1];
  203. }
  204.  
  205. =item C<$et = $set-E<gt>false>
  206.  
  207. Return 1 iff the C<DisjConditions> object is always false (i.e., if it
  208. is empty, or if it contains only false C<Condition>s). Return 0
  209. otherwise.
  210.  
  211. =cut
  212.  
  213. sub false ($ )
  214. {
  215.   my ($self) = @_;
  216.   return 0 == keys %{$self->{'hash'}};
  217. }
  218.  
  219. =item C<$et = $set-E<gt>true>
  220.  
  221. Return 1 iff the C<DisjConditions> object is always true (i.e. covers all
  222. conditions). Return 0 otherwise.
  223.  
  224. =cut
  225.  
  226. sub true ($ )
  227. {
  228.   my ($self) = @_;
  229.   return $self->invert->false;
  230. }
  231.  
  232. =item C<$str = $set-E<gt>string>
  233.  
  234. Build a string which denotes the C<DisjConditions>.
  235.  
  236. =cut
  237.  
  238. sub string ($ )
  239. {
  240.   my ($self) = @_;
  241.  
  242.   return $self->{'string'} if defined $self->{'string'};
  243.  
  244.   my $res = '';
  245.   if ($self->false)
  246.     {
  247.       $res = 'FALSE';
  248.     }
  249.   else
  250.     {
  251.       $res = join (' | ', map { $_->string } $self->conds);
  252.     }
  253.  
  254.   $self->{'string'} = $res;
  255.   return $res;
  256. }
  257.  
  258. =item C<$cond-E<gt>human>
  259.  
  260. Build a human readable string which denotes the C<DisjConditions>.
  261.  
  262. =cut
  263.  
  264. sub human ($ )
  265. {
  266.   my ($self) = @_;
  267.  
  268.   return $self->{'human'} if defined $self->{'human'};
  269.  
  270.   my $res = '';
  271.   if ($self->false)
  272.     {
  273.       $res = 'FALSE';
  274.     }
  275.   else
  276.     {
  277.       my @c = $self->conds;
  278.       if (1 == @c)
  279.     {
  280.       $res = $c[0]->human;
  281.     }
  282.       else
  283.     {
  284.       $res = '(' . join (') or (', map { $_->human } $self->conds) . ')';
  285.     }
  286.     }
  287.   $self->{'human'} = $res;
  288.   return $res;
  289. }
  290.  
  291.  
  292. =item C<$prod = $set1-E<gt>multiply ($set2)>
  293.  
  294. Multiply two conditional sets.
  295.  
  296.   my $set1 = new Automake::DisjConditions
  297.     (new Automake::Condition ("A_TRUE"),
  298.      new Automake::Condition ("B_TRUE"));
  299.   my $set2 = new Automake::DisjConditions
  300.     (new Automake::Condition ("C_FALSE"),
  301.      new Automake::Condition ("D_FALSE"));
  302.  
  303. C<$set1-E<gt>multiply ($set2)> will return
  304.  
  305.   new Automake::DisjConditions
  306.     (new Automake::Condition ("A_TRUE", "C_FALSE"),
  307.      new Automake::Condition ("B_TRUE", "C_FALSE"),;
  308.      new Automake::Condition ("A_TRUE", "D_FALSE"),
  309.      new Automake::Condition ("B_TRUE", "D_FALSE"));
  310.  
  311. The argument can also be a C<Condition>.
  312.  
  313. =cut
  314.  
  315. # Same as multiply() but take a list of Conditonals as second argument.
  316. # We use this in invert().
  317. sub _multiply ($@)
  318. {
  319.   my ($self, @set) = @_;
  320.   my @res = map { $_->multiply (@set) } $self->conds;
  321.   return new Automake::DisjConditions (Automake::Condition::reduce_or @res);
  322. }
  323.  
  324. sub multiply ($$)
  325. {
  326.   my ($self, $set) = @_;
  327.   return $self->_multiply ($set) if $set->isa('Automake::Condition');
  328.   return $self->_multiply ($set->conds);
  329. }
  330.  
  331. =item C<$inv = $set-E<gt>invert>
  332.  
  333. Invert a C<DisjConditions>.  Return a C<DisjConditions> which is true
  334. when C<$set> is false, and vice-versa.
  335.  
  336.   my $set = new Automake::DisjConditions
  337.     (new Automake::Condition ("A_TRUE", "B_TRUE"),
  338.      new Automake::Condition ("A_FALSE", "B_FALSE"));
  339.  
  340. Calling C<$set-E<gt>invert> will return the following C<DisjConditions>.
  341.  
  342.   new Automake::DisjConditions
  343.     (new Automake::Condition ("A_TRUE", "B_FALSE"),
  344.      new Automake::Condition ("A_FALSE", "B_TRUE"));
  345.  
  346. We implement the inversion by a product-of-sums to sum-of-products
  347. conversion using repeated multiplications.  Because of the way we
  348. implement multiplication, the result of inversion is in canonical
  349. prime implicant form.
  350.  
  351. =cut
  352.  
  353. sub invert($ )
  354. {
  355.   my ($self) = @_;
  356.  
  357.   return $self->{'invert'} if defined $self->{'invert'};
  358.  
  359.   # The invert of an empty DisjConditions is TRUE.
  360.   my $res = new Automake::DisjConditions TRUE;
  361.  
  362.   #   !((a.b)+(c.d)+(e.f))
  363.   # = (!a+!b).(!c+!d).(!e+!f)
  364.   # We develop this into a sum of product iteratively, starting from TRUE:
  365.   # 1) TRUE
  366.   # 2) TRUE.!a + TRUE.!b
  367.   # 3) TRUE.!a.!c + TRUE.!b.!c + TRUE.!a.!d + TRUE.!b.!d
  368.   # 4) TRUE.!a.!c.!e + TRUE.!b.!c.!e + TRUE.!a.!d.!e + TRUE.!b.!d.!e
  369.   #    + TRUE.!a.!c.!f + TRUE.!b.!c.!f + TRUE.!a.!d.!f + TRUE.!b.!d.!f
  370.   foreach my $cond ($self->conds)
  371.     {
  372.       $res = $res->_multiply ($cond->not);
  373.     }
  374.  
  375.   # Cache result.
  376.   $self->{'invert'} = $res;
  377.   # It's tempting to also set $res->{'invert'} to $self, but that
  378.   # is a bad idea as $self hasn't been normalized in any way.
  379.   # (Different inputs can produce the same inverted set.)
  380.   return $res;
  381. }
  382.  
  383. =item C<$self-E<gt>simplify>
  384.  
  385. Return a C<Disjunction> which is a simplified canonical form of C<$self>.
  386. This canonical form contains only prime implicants, but it can contain
  387. non-essential prime implicants.
  388.  
  389. =cut
  390.  
  391. sub simplify ($)
  392. {
  393.   my ($self) = @_;
  394.   return $self->invert->invert;
  395. }
  396.  
  397. =item C<$self-E<gt>sub_conditions ($cond)>
  398.  
  399. Return the subconditions of C<$self> that contains C<$cond>, with
  400. C<$cond> stripped.  More formally, return C<$res> such that
  401. C<$res-E<gt>multiply ($cond) == $self-E<gt>multiply ($cond)> and
  402. C<$res> does not mention any of the variables in C<$cond>.
  403.  
  404. For instance, consider:
  405.  
  406.   my $a = new Automake::DisjConditions
  407.     (new Automake::Condition ("A_TRUE", "B_TRUE"),
  408.      new Automake::Condition ("A_TRUE", "C_FALSE"),
  409.      new Automake::Condition ("A_TRUE", "B_FALSE", "C_TRUE"),
  410.      new Automake::Condition ("A_FALSE"));
  411.   my $b = new Automake::DisjConditions
  412.     (new Automake::Condition ("A_TRUE", "B_FALSE"));
  413.  
  414. Calling C<$a-E<gt>sub_conditions ($b)> will return the following
  415. C<DisjConditions>.
  416.  
  417.   new Automake::DisjConditions
  418.     (new Automake::Condition ("C_FALSE"), # From A_TRUE C_FALSE
  419.      new Automake::Condition ("C_TRUE")); # From A_TRUE B_FALSE C_TRUE"
  420.  
  421. =cut
  422.  
  423. sub sub_conditions ($$)
  424. {
  425.   my ($self, $subcond) = @_;
  426.  
  427.   # Make $subcond blindingly apparent in the DisjConditions.
  428.   # For instance `$b->multiply($a->conds)' (from the POD example) is:
  429.   #     (new Automake::Condition ("FALSE"),
  430.   #      new Automake::Condition ("A_TRUE", "B_FALSE", "C_FALSE"),
  431.   #      new Automake::Condition ("A_TRUE", "B_FALSE", "C_TRUE"),
  432.   #      new Automake::Condition ("FALSE"))
  433.   my @prodconds = $subcond->multiply ($self->conds);
  434.  
  435.   # Now, strip $subcond from the remaining (i.e., non-false) Conditions.
  436.   my @res = map { $_->false ? () : $_->strip ($subcond) } @prodconds;
  437.  
  438.   return new Automake::DisjConditions @res;
  439. }
  440.  
  441. =item C<($string, $ambig_cond) = $condset-E<gt>ambiguous_p ($what, $cond)>
  442.  
  443. Check for an ambiguous condition.  Return an error message and the
  444. other condition involved if we have an ambiguity.  Return an empty
  445. string and FALSE otherwise.
  446.  
  447. C<$what> is the name of the thing being defined, to use in the error
  448. message.  C<$cond> is the C<Condition> under which it is being
  449. defined.  C<$condset> is the C<DisjConditions> under which it had
  450. already been defined.
  451.  
  452. =cut
  453.  
  454. sub ambiguous_p ($$$)
  455. {
  456.   my ($self, $var, $cond) = @_;
  457.  
  458.   # Note that these rules don't consider the following
  459.   # example as ambiguous.
  460.   #
  461.   #   if COND1
  462.   #     FOO = foo
  463.   #   endif
  464.   #   if COND2
  465.   #     FOO = bar
  466.   #   endif
  467.   #
  468.   # It's up to the user to not define COND1 and COND2
  469.   # simultaneously.
  470.  
  471.   return ("$var multiply defined in condition " . $cond->human, $cond)
  472.     if exists $self->{'hash'}{$cond};
  473.  
  474.   foreach my $vcond ($self->conds)
  475.     {
  476.       return ("$var was already defined in condition " . $vcond->human
  477.           . ", which includes condition ". $cond->human, $vcond)
  478.     if $vcond->true_when ($cond);
  479.  
  480.       return ("$var was already defined in condition " . $vcond->human
  481.           . ", which is included in condition " . $cond->human, $vcond)
  482.     if $cond->true_when ($vcond);
  483.     }
  484.   return ('', FALSE);
  485. }
  486.  
  487. =head1 SEE ALSO
  488.  
  489. L<Automake::Condition>.
  490.  
  491. =head1 HISTORY
  492.  
  493. C<AM_CONDITIONAL>s and supporting code were added to Automake 1.1o by
  494. Ian Lance Taylor <ian@cygnus.org> in 1997.  Since then it has been
  495. improved by Tom Tromey <tromey@redhat.com>, Richard Boulton
  496. <richard@tartarus.org>, Raja R Harinath <harinath@cs.umn.edu>, Akim
  497. Demaille <akim@epita.fr>, Pavel Roskin <proski@gnu.org>, and
  498. Alexandre Duret-Lutz <adl@gnu.org>.
  499.  
  500. =cut
  501.  
  502. 1;
  503.  
  504. ### Setup "GNU" style for perl-mode and cperl-mode.
  505. ## Local Variables:
  506. ## perl-indent-level: 2
  507. ## perl-continued-statement-offset: 2
  508. ## perl-continued-brace-offset: 0
  509. ## perl-brace-offset: 0
  510. ## perl-brace-imaginary-offset: 0
  511. ## perl-label-offset: -2
  512. ## cperl-indent-level: 2
  513. ## cperl-brace-offset: 0
  514. ## cperl-continued-brace-offset: 0
  515. ## cperl-label-offset: -2
  516. ## cperl-extra-newline-before-brace: t
  517. ## cperl-merge-trailing-else: nil
  518. ## cperl-continued-statement-offset: 2
  519. ## End:
  520.